package com.luqili.utils.pub.array;

import cn.hutool.core.util.ObjectUtil;

import java.lang.reflect.Array;
import java.util.Arrays;


/**
 * byte[] 的处理方案
 *
 * @author luqili
 */
public class ByteArrayTools {
    public static final int INDEX_NOT_FOUND = -1;

    /**
     * 数组是否为空
     *
     * @param array 数组
     * @return 是否为空
     */
    public static boolean isEmpty(byte[] array) {
        return array == null || array.length == 0;
    }

    /**
     * 数组是否为非空
     *
     * @param array 数组
     * @return 是否为非空
     */
    public static boolean isNotEmpty(byte[] array) {
        return (null != array && array.length != 0);
    }

    public static int indexOf(byte[] array, byte value) {
        if (null != array) {
            for (int i = 0; i < array.length; i++) {
                if (value == array[i]) {
                    return i;
                }
            }
        }
        return INDEX_NOT_FOUND;
    }

    /**
     * 返回数组中指定元素所在位置，未找到返回{@link #INDEX_NOT_FOUND}
     *
     * @param array             数组
     * @param value             被检查的元素
     * @param beginIndexInclude 检索开始的位置
     * @return 数组中指定元素所在位置，未找到返回{@link #INDEX_NOT_FOUND}
     * @since 3.0.7
     */
    public static int indexOf(byte[] array, byte value, int beginIndexInclude) {
        for (int i = beginIndexInclude; i < array.length; i++) {
            if (array[i] == value) {
                return i;
            }
        }
        return INDEX_NOT_FOUND;
    }


    /**
     * 返回数组中指定元素所在最后的位置，未找到返回{@link #INDEX_NOT_FOUND}
     *
     * @param array 数组
     * @param value 被检查的元素
     * @return 数组中指定元素所在位置，未找到返回{@link #INDEX_NOT_FOUND}
     * @since 3.0.7
     */
    public static int lastIndexOf(byte[] array, byte value) {
        if (isEmpty(array)) {
            return INDEX_NOT_FOUND;
        }
        return lastIndexOf(array, value, array.length - 1);
    }

    /**
     * 返回数组中指定元素所在最后的位置，未找到返回{@link #INDEX_NOT_FOUND}
     *
     * @param array      数组
     * @param value      被检查的元素
     * @param endInclude 查找方式为从后向前查找，查找的数组结束位置，一般为array.length-1
     * @return 数组中指定元素所在位置，未找到返回{@link #INDEX_NOT_FOUND}
     * @since 5.7.3
     */
    public static int lastIndexOf(byte[] array, byte value, int endInclude) {
        if (isNotEmpty(array)) {
            for (int i = endInclude; i >= 0; i--) {
                if (array[i] == value) {
                    return i;
                }
            }
        }
        return INDEX_NOT_FOUND;
    }

    /**
     * 查找子数组的位置
     *
     * @param array    数组
     * @param subArray 子数组
     * @return 子数组的开始位置，即子数字第一个元素在数组中的位置
     */
    public static int indexOfSub(byte[] array, byte[] subArray) {
        return indexOfSub(array, 0, subArray);
    }

    /**
     * 查找子数组的位置
     *
     * @param array        数组
     * @param beginInclude 查找开始的位置（包含）
     * @param subArray     子数组
     * @return 子数组的开始位置，即子数字第一个元素在数组中的位置
     * @since 5.4.8
     */
    public static int indexOfSub(byte[] array, int beginInclude, byte[] subArray) {
        if (isEmpty(array) || isEmpty(subArray) || subArray.length > array.length) {
            return INDEX_NOT_FOUND;
        }
        int firstIndex = indexOf(array, subArray[0], beginInclude);
        if (firstIndex < 0 || firstIndex + subArray.length > array.length) {
            return INDEX_NOT_FOUND;
        }
        for (int i = 0; i < subArray.length; i++) {
            if (false == ObjectUtil.equal(array[i + firstIndex], subArray[i])) {
                return indexOfSub(array, firstIndex + 1, subArray);
            }
        }
        return firstIndex;
    }


    /**
     * 查找最后一个子数组的开始位置
     *
     * @param array    数组
     * @param subArray 子数组
     * @return 最后一个子数组的开始位置，即子数字第一个元素在数组中的位置
     */
    public static int lastIndexOfSub(byte[] array, byte[] subArray) {
        if (isEmpty(array) || isEmpty(subArray)) {
            return INDEX_NOT_FOUND;
        }
        return lastIndexOfSub(array, array.length - 1, subArray);
    }

    /**
     * 查找最后一个子数组的开始位置
     *
     * @param array      数组
     * @param endInclude 查找结束的位置（包含）
     * @param subArray   子数组
     * @return 最后一个子数组的开始位置，即子数字第一个元素在数组中的位置
     * @since 5.4.8
     */
    public static int lastIndexOfSub(byte[] array, int endInclude, byte[] subArray) {
        if (isEmpty(array) || isEmpty(subArray) || subArray.length > array.length || endInclude < 0) {
            return INDEX_NOT_FOUND;
        }

        int maxI = array.length - subArray.length;
        for (int i = maxI; i >= 0; i--) {
            boolean have = true;
            for (int j = 0; j < subArray.length; j++) {
                if (array[i + j] != subArray[j]) {
                    have = false;
                    break;
                }
            }
            if (have) {
                return i;
            }
        }
        return INDEX_NOT_FOUND;
    }

    /**
     * 获取子数组
     *
     * @param array 数组
     * @param start 开始位置（包括）
     * @param end   结束位置（不包括）
     * @return 新的数组
     */
    public static byte[] sub(byte[] array, int start, int end) {
        int length = Array.getLength(array);
        if (start < 0) {
            start += length;
        }
        if (end < 0) {
            end += length;
        }
        if (start == length) {
            return new byte[0];
        }
        if (start > end) {
            int tmp = start;
            start = end;
            end = tmp;
        }
        if (end > length) {
            if (start >= length) {
                return new byte[0];
            }
            end = length;
        }
        return Arrays.copyOfRange(array, start, end);
    }

    /**
     * 根据字节匹配，获取子数组
     *
     * @param array 数组
     * @param start 开始位置（包括）
     * @param end   结束位置（不包括）
     * @return
     */
    public static byte[] sub(byte[] array, byte[] start, byte[] end) {
        int indexS = indexOfSub(array, start);
        if (indexS < 0) {
            return new byte[0];
        }
        int indexE = lastIndexOfSub(array, end);
        if (indexE < 0) {
            return new byte[0];
        }
        return sub(array, indexS, indexE + end.length);
    }


    /**
     * 反转数组，
     *
     * @param array 不会修改原数组
     * @return 反转后新的数组
     */
    public static byte[] reverseCopy(byte[] array) {
        byte[] cp = new byte[array.length];
        for (int i = 0; i < cp.length; i++) {
            cp[i] = array[array.length - 1 - i];
        }
        return cp;
    }

    /**
     * 复制一个一样的新数组
     *
     * @param array
     * @return
     */
    public static byte[] copy(byte[] array) {
        byte[] cp = new byte[array.length];
        for (int i = 0; i < cp.length; i++) {
            cp[i] = array[i];
        }
        return cp;
    }


}
